
#include <BVBoxLayout>
#include <BHBoxLayout>
#include <BPainter>
#include <BStyle>
#include <BFont>
#include <BLabel>

#include <BHtmlItem>
#include "member_BHtmlItem.h"
#include "member_BXmlNode.h"
#include "member_BHtmlWidget.h"

using namespace BWE;

#define member					(*(member_BHtmlItem*)_ptr)
#define member_allocate()		_ptr = new member_BHtmlItem(this)
#define member_release()		delete (member_BHtmlItem*)_ptr

BHtmlItem::BHtmlItem(BHtmlItem* parent)
{
	member_allocate();
	if (parent)
		parent->addChild(this);
}
BHtmlItem::BHtmlItem(const BString& name, BHtmlItem* parent) : BXmlNode(name)
{
	member_allocate();
	if (parent)
		parent->addChild(this);
}
BHtmlItem::BHtmlItem(BXmlNode* node, BHtmlItem* parent)
{
	member_allocate();
	this->setName(node->name());
	this->setText(node->text());
	this->setFormat(node->format());
	xml_member(this)->attribSet = xml_member(node)->attribSet;
	for (int i = 0; i < node->childCount(); i++)
	{
		BXmlNode* childNode = node->child(i);
		BHtmlItem* child = new BHtmlItem(childNode);
		this->addChild(child);
	}
	member.dirtyHtml();
	if (parent)
		parent->addChild(this);
}
BHtmlItem::~BHtmlItem()
{
	member_release();
}

bool BHtmlItem::setName(const BString& name)
{
	if (BObject::setName(name))
	{
		if (member.htmlWidget)
		{
			html_member(member.htmlWidget)->freshStyle(this);
		}
		member.dirtyHtml();
		return true;
	}
	return false;
}
bool BHtmlItem::setFormat(const BString& format)
{
	if (BXmlNode::setFormat(format))
	{
		member.dirtyHtml();
		return true;
	}
	return false;
}
bool BHtmlItem::setText(const BString& text)
{
	if (BXmlNode::setText(text))
	{
		member.block.text = text;
		ConvertHtmlToText(member.block.text);
		member.block.reset(member.block.text);
		member.dirtyHtml();
		return true;
	}
	return false;
}
bool BHtmlItem::setAttrib(const BString& name, const BString& value)
{
	if (BXmlNode::setAttrib(name, value))
	{
		const BString& widthText = this->attrib("width");
		member.fixedWidth = widthText.toInt();

		const BString& heightText = this->attrib("height");
		member.fixedHeight = heightText.toInt();

		member.dirtyHtml();
		return true;
	}
	return false;
}

void BHtmlItem::setSelected(bool selected)
{
	if (member.htmlWidget)
	{
		member.htmlWidget->setItemSelected(this, selected);
	}
}
bool BHtmlItem::selected() const
{
	if (member.htmlWidget)
	{
		return member.htmlWidget->selectedItem() == this;
	}
	return false;
}

const BRect& BHtmlItem::rect() const
{
	if (member.htmlWidget)
		member.abRect = member.rect + member.htmlWidget->area().pos();
	return member.abRect;
}
const BFont* BHtmlItem::font() const
{
	return member.block.font();
}

BHtmlWidget* BHtmlItem::htmlWidget()
{
	return member.htmlWidget;
}
const BHtmlWidget* BHtmlItem::htmlWidget() const
{
	return member.htmlWidget;
}

BHtmlItem* BHtmlItem::parent()
{
	return dynamic_cast<BHtmlItem*>(BXmlNode::parent());
}
const BHtmlItem* BHtmlItem::parent() const
{
	return dynamic_cast<const BHtmlItem*>(BXmlNode::parent());
}

BHtmlItem* BHtmlItem::parent(const BString& name)
{
	return dynamic_cast<BHtmlItem*>(BXmlNode::parent(name));
}
const BHtmlItem* BHtmlItem::parent(const BString& name) const
{
	return dynamic_cast<const BHtmlItem*>(BXmlNode::parent(name));
}

bool BHtmlItem::addChild(BHtmlItem* item)
{
	if (!item)
		return false;
	if (this == item)
		return false;
	if (BXmlNode::addChild(item))
	{
		item_member(item)->htmlWidget = member.htmlWidget;
		member.dirtyHtml();
		if (member.htmlWidget)
			html_member(member.htmlWidget)->freshStyle(item);
	}
	return true;
}
bool BHtmlItem::insertChild(int pos, BHtmlItem* item)
{
	if (BXmlNode::insertChild(pos, item))
	{
		item_member(item)->htmlWidget = member.htmlWidget;
		member.dirtyHtml();
		if (member.htmlWidget)
			html_member(member.htmlWidget)->freshStyle(item);
		return true;
	}
	return false;
}
bool BHtmlItem::removeChild(const BHtmlItem* item)
{
	if (BXmlNode::removeChild(item))
	{
		item_member(item)->htmlWidget = 0;
		if (member.htmlWidget)
			member.htmlWidget->fresh();
		member.dirtyHtml();
		return true;
	}
	return false;
}

BHtmlItem* BHtmlItem::child(int index)
{
	return dynamic_cast<BHtmlItem*>(BXmlNode::child(index));
}
const BHtmlItem* BHtmlItem::child(int index) const
{
	return dynamic_cast<const BHtmlItem*>(BXmlNode::child(index));
}
